/* Mobile-only chrome. On a phone the sidebar stacks to ~2200px, so without a
   persistent bar the nav is unreachable once you scroll, and without a fixed
   CTA the only way to contact anyone is to scroll back up. */

function MobileBar({ s, t, onNavigate, onMenu, menuOpen, dark = false, screen }) {
  /* Publish the bar's real height for the layout below it. Ref callback +
     state so the observer always holds the live node, plus window resize as
     a belt-and-braces republish. */
  const [barEl, setBarEl] = React.useState(null);
  React.useEffect(() => {
    if (!barEl) return;
    const publish = () => document.documentElement.style.setProperty('--mobile-bar-h', `${Math.ceil(barEl.getBoundingClientRect().height)}px`);
    publish();
    let ro;
    if (typeof ResizeObserver !== 'undefined') { ro = new ResizeObserver(publish); ro.observe(barEl); }
    window.addEventListener('resize', publish);
    window.addEventListener('load', publish);
    return () => { if (ro) ro.disconnect(); window.removeEventListener('resize', publish); window.removeEventListener('load', publish); };
  }, [barEl]);
  const { Logo, LangSwitch, MenuButton } = window.SevcikMarketingDesignSystem_3203fa;
  const [solid, setSolid] = React.useState(false);
  const [hidden, setHidden] = React.useState(false);

  /* Hide going down, return going up.

     Three things this has to survive, all of which broke earlier versions:
     - the transform must come from state, not a direct style write, or the
       re-render that setSolid triggers immediately clobbers it;
     - layered screens scroll their own element rather than the window, and that
       element is replaced whenever a layer mounts - so instead of capturing a
       node we listen on document in the CAPTURE phase, which receives scroll
       from any descendant (scroll does not bubble, but it does capture). Bound
       once, never re-bound, impossible to lose;
     - the previous position lives in a ref and is re-synced on every event,
       because the readers and the route effect both reset scrollTop behind our
       back and a captured `prev` drifts permanently out of date.

     Plus an unconditional floor: at or below 140px the bar is always shown, so
     no bookkeeping error can leave it stranded off-screen. */
  const prev = React.useRef(0);

  const isHome = screen === 'home';
  const screenRef = React.useRef(screen);
  screenRef.current = screen;
  React.useEffect(() => {
    prev.current = 0;
    setHidden(false);
    setSolid(false);
    /* Home scrubs the bar continuously with scroll (see onScroll); the
       @property transition must be off there or it lags the finger. */
    document.documentElement.classList.toggle('sm-bar-scrub', isHome);
    if (!isHome) document.documentElement.style.setProperty('--bar-hidden', '0');
  }, [screen]);

  React.useEffect(() => {
    const onScroll = (e) => {
      const t = e.target;
      /* Horizontal scrollers (chapter strip, highlights) fire scroll events too;
         their scrollTop is 0, which would drag the bar back down mid-page. */
      if (t && t.nodeType === 1 && t !== document.documentElement && (t.scrollHeight - t.clientHeight) < 8) return;
      const y = (!t || t === document || t === document.documentElement || t === window)
        ? window.scrollY
        : (t.scrollTop || 0);
      setSolid(y > 24);
      /* Home hero zone (first ~half screen): the bar rides the scroll
         clock continuously with the hero push - rate-limited so re-entering
         the zone mid-page never snaps it. Deeper in the page the scrub
         class comes off and the bar goes back to the reactive
         hide-down/show-up behaviour, smoothed by the @property transition. */
      const home = screenRef.current === 'home';
      const docStyle = document.documentElement.style;
      if (home && y < window.innerHeight * 0.5) {
        const vh = window.innerHeight;
        document.documentElement.classList.add('sm-bar-scrub');
        const target = Math.max(0, Math.min(1, (y - vh * 0.05) / (vh * 0.2)));
        const cur = parseFloat(docStyle.getPropertyValue('--bar-hidden')) || 0;
        const step = Math.max(-0.09, Math.min(0.09, target - cur));
        docStyle.setProperty('--bar-hidden', (cur + step).toFixed(3));
        prev.current = y;
        return;
      }
      if (home) document.documentElement.classList.remove('sm-bar-scrub');
      if (y <= 140) { prev.current = y; setHidden(false); if (home) docStyle.setProperty('--bar-hidden', '0'); return; }
      const delta = y - prev.current;
      if (Math.abs(delta) < 6) return;
      prev.current = y;
      setHidden(delta > 0);
      if (home) docStyle.setProperty('--bar-hidden', delta > 0 ? '1' : '0');
    };
    document.addEventListener('scroll', onScroll, { capture: true, passive: true });
    return () => document.removeEventListener('scroll', onScroll, { capture: true });
  }, []);

  /* Publish the hidden state for the hero on non-home screens only - home
     writes a continuous fraction from its scroll handler instead. */
  React.useEffect(() => {
    if (isHome) return;
    document.documentElement.style.setProperty('--bar-hidden', hidden && !menuOpen ? '1' : '0');
  }, [hidden, menuOpen, isHome]);

  const solidBg = dark
    ? 'color-mix(in srgb, var(--ink-850) 92%, transparent)'
    : 'color-mix(in srgb, var(--paper) 92%, transparent)';
  const hair = dark ? 'var(--border-hairline-dark)' : 'var(--gray-200)';

  return (
    <div className="sm-mobile-bar" ref={setBarEl} style={{
      position: 'fixed', top: 0, left: 0, right: 0, zIndex: 40,
      display: 'none', alignItems: 'center', justifyContent: 'space-between', gap: 12,
      padding: '8px 12px', minHeight: 60,
      backgroundColor: solidBg,
      backdropFilter: 'blur(14px)',
      borderBottom: `1.5px solid ${hair}`,
      transform: isHome && !menuOpen ? 'translateY(calc(var(--bar-hidden, 0) * -105%))' : (hidden && !menuOpen ? 'translateY(-105%)' : 'translateY(0)'),
      transition: isHome ? 'background-color .3s ease, border-color .3s ease' : 'transform .35s cubic-bezier(.22,1,.36,1), background-color .3s ease, border-color .3s ease',
    }}>
      <a href={routeHref({ lang: s.htmlLang, screen: 'home' })} onClick={(e) => { e.preventDefault(); onNavigate('home'); }} style={{ display: 'flex', alignItems: 'center', minHeight: 44 }}>
        <Logo size={44} variant={dark ? 'light' : 'dark'} />
      </a>
      <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
        <LangSwitch value={s.code} tall dark={dark} onChange={(c) => onNavigate({ lang: c })} />
        <MenuButton open={menuOpen} onClick={onMenu} label={t.menu} size={44} dark={dark} />
      </div>
    </div>
  );
}

function MobileCta({ t, onContact, closed, onClose }) {
  const ref = React.useRef(null);
  /* Dismissable: a reader who has decided not to be sold to can close the bar,
     and a small envelope takes its place in the corner so the way to contact
     never actually disappears. */

  /* Hidden until the reader has scrolled past most of the hero - the fold
     stays a cover, the ask arrives once there's interest. */
  const [shown, setShown] = React.useState(false);
  React.useEffect(() => {
    const onScroll = (e) => {
      const el = e.target;
      if (el && el.nodeType === 1 && el !== document.documentElement && (el.scrollHeight - el.clientHeight) < 8) return;
      const y = (!el || el === document || el === document.documentElement || el === window) ? window.scrollY : (el.scrollTop || 0);
      setShown(y > window.innerHeight * 0.45);
    };
    document.addEventListener('scroll', onScroll, { capture: true, passive: true });
    return () => document.removeEventListener('scroll', onScroll, { capture: true });
  }, []);
  React.useEffect(() => {
    const el = ref.current;
    if (!el || typeof ResizeObserver === 'undefined') return;
    const publish = () => document.documentElement.style.setProperty('--mobile-cta-h', `${Math.round(el.getBoundingClientRect().height)}px`);
    const ro = new ResizeObserver(publish);
    ro.observe(el);
    publish();
    return () => ro.disconnect();
  }, []);
  return (
    <div className="sm-mobile-cta" ref={ref} style={{
      position: 'fixed', left: 10, right: 10, bottom: 10, zIndex: 45,
      display: 'none', alignItems: 'center', gap: 8,
      flexDirection: 'column', alignItems: 'stretch', gap: 0,
      transform: (shown && !closed) ? 'translateY(0)' : 'translateY(calc(100% + 34px))',
      transition: 'transform .45s cubic-bezier(.22,1,.36,1)',
    }}>
      {/* Above the bar, hard left. Barely there until you look for it - a
          dismissal, not an action. */}
      <button onClick={onClose} aria-label={t.dismiss || 'Hide'} style={{
        alignSelf: 'flex-start', width: 30, height: 30, marginBottom: 4, padding: 0, cursor: 'pointer',
        border: 'none', background: 'transparent', display: 'flex', alignItems: 'center', justifyContent: 'center',
        opacity: 0.34,
      }}>
        <svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="var(--black)" strokeWidth="1.6" strokeLinecap="round"><path d="M2 2l8 8M10 2l-8 8" /></svg>
      </button>
      <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
      <button onClick={onContact} style={{
        flex: 1, minHeight: 50, cursor: 'pointer',
        border: '1.5px solid rgba(10,10,10,0.1)', borderRadius: 'var(--radius-card)',
        background: 'color-mix(in srgb, var(--white) 82%, transparent)',
        backdropFilter: 'blur(16px)', WebkitBackdropFilter: 'blur(16px)',
        color: 'var(--black)',
        fontFamily: 'var(--font-display)', fontWeight: 500, fontSize: 16, letterSpacing: '-0.01em',
        boxShadow: '0 6px 20px rgba(10,10,10,0.1)',
      }}>{t.bookCall}</button>
      <a href={`https://wa.me/${CONTACT.whatsapp.replace(/[^\d]/g, '')}`} target="_blank" rel="noopener noreferrer"
        aria-label="WhatsApp"
        style={{
          width: 74, height: 50, flexShrink: 0, borderRadius: 'var(--radius-card)',
          border: '1.5px solid rgba(10,10,10,0.1)',
          background: 'color-mix(in srgb, var(--white) 82%, transparent)',
          backdropFilter: 'blur(16px)', WebkitBackdropFilter: 'blur(16px)',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          boxShadow: '0 6px 20px rgba(10,10,10,0.1)',
        }}>
        {React.createElement(window.SevcikMarketingDesignSystem_3203fa.Icon, { name: 'whatsapp', size: 22, color: 'var(--black)' })}
      </a>
      </div>
    </div>
  );
}

/* Once the bar is dismissed, this is the only way back to contact - bottom
   LEFT, opposite the thumb's default resting corner, so it reads as available
   rather than pushy. */
function MobileMailDot({ shown, onContact, label }) {
  return (
    <button onClick={onContact} aria-label={label} className="sm-mobile-maildot" style={{
      position: 'fixed', left: 12, bottom: 12, zIndex: 44,
      width: 40, height: 40, borderRadius: '50%', cursor: 'pointer',
      border: '1px solid rgba(10,10,10,0.07)',
      background: 'color-mix(in srgb, var(--white) 62%, transparent)',
      backdropFilter: 'blur(12px)', WebkitBackdropFilter: 'blur(12px)',
      display: 'none', alignItems: 'center', justifyContent: 'center',
      boxShadow: 'none',
      opacity: shown ? 0.42 : 0,
      transform: shown ? 'translateY(0) scale(1)' : 'translateY(10px) scale(0.9)',
      transition: 'opacity .35s ease, transform .4s cubic-bezier(.22,1,.36,1)',
      pointerEvents: shown ? 'auto' : 'none',
    }}>
      <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="var(--black)" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><rect x="2.5" y="5" width="19" height="14" rx="2.5" /><path d="M3.5 7l8.5 6 8.5-6" /></svg>
    </button>
  );
}

Object.assign(window, { MobileBar, MobileCta, MobileMailDot });
